package com.groupYLP.CouponNexus.gateway.filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.UUID;

/**
 * 全局请求过滤器
 */
@Component
public class RequestLoggingFilter implements GlobalFilter, Ordered {

    private static final Logger LOG = LoggerFactory.getLogger(RequestLoggingFilter.class);

    /**
     * 自定义网关过滤器，用于处理每一个经过的请求
     * 该过滤器主要目的是记录请求的详细信息以及计算请求的处理时间
     *
     * @param exchange 服务器Web交换对象，包含请求和响应的所有信息
     * @param chain 过滤器链对象，用于将控制权转交给下一个过滤器
     * @return Mono<Void> 表示异步处理完成的响应
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取当前请求对象
        ServerHttpRequest request = exchange.getRequest();
        // 获取请求的方法类型
        HttpMethod method = request.getMethod();

        // 生成唯一的追踪ID，用于标识和跟踪请求
        String traceId = UUID.randomUUID().toString();

        // 记录请求开始的时间
        long startTime = System.currentTimeMillis();
        // 将追踪ID放入MDC中，以便在日志中进行关联
        MDC.put("traceId", traceId);

        // 记录请求的详细信息
        LOG.info("请求URI： {}", request.getURI());
        LOG.info("请求类型：{}", method);
        LOG.info("请求头：{}", request.getHeaders());

        // 如果请求方法是GET，则记录GET请求的参数
        if (method == HttpMethod.GET) {
            LOG.info("请求参数：{}", request.getQueryParams());
        }

        // 请求响应然后执行
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            // 计算请求处理时间
            long duration = System.currentTimeMillis() - startTime;
            // 记录请求处理时间
            LOG.info("响应时间：{} ms", duration);
        }));
    }


    /**
     * 返回当前对象的顺序值
     *
     * 顺序值用于确定对象在某些操作中的处理顺序
     * 返回-1表示该对象应被视为具有最高优先级或最先处理
     *
     * @return int 表示顺序值的整数，-1代表最高优先级
     */
    @Override
    public int getOrder() {
        return -1;
    }
}
